package cn.sdack.go.users.service;

import cn.sdack.go.common.annotation.AfterAuthentication;
import cn.sdack.go.common.annotation.BeforeAuthentication;
import cn.sdack.go.common.entities.users.AuthorityEntity;
import cn.sdack.go.common.entities.users.RoleAuthorityEntity;
import cn.sdack.go.common.entities.users.UserAuthorityEntity;
import cn.sdack.go.common.querys.users.AuthorityQuery;
import cn.sdack.go.users.dao.AuthorityDao;
import cn.sdack.go.users.dao.RoleAuthorityDao;
import cn.sdack.go.users.dao.UserAuthorityDao;
import com.alibaba.fastjson2.JSONObject;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Locale;
import java.util.Optional;

import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers.endsWith;

/**
 * @author sdack
 * @date 2024/1/9
 */
@Service
public class AuthorityServiceImpl  implements AuthorityService {

    @Autowired
    private AuthorityDao authorityDao;

    @Autowired
    private RoleAuthorityDao roleAuthorityDao;

    @Autowired
    private UserAuthorityDao userAuthorityDao;

    private final List<String> defaultCode = List.of("group","super"); // 保留值


    @BeforeAuthentication
    @Override
    public Page<AuthorityEntity> queryAll(AuthorityQuery param, int page, int pageSize) {
        ExampleMatcher matcher = ExampleMatcher.matchingAny()
                .withIgnoreNullValues()
                .withMatcher(AuthorityQuery.CODE, endsWith());

        AuthorityEntity query = JSONObject.parseObject(JSONObject.toJSONString(param), AuthorityEntity.class);
        Example<AuthorityEntity> example = Example.of(query, matcher);
        return authorityDao.findAll(example, PageRequest.of(page <= 0 ? 0 : page - 1, pageSize, Sort.by(Sort.Order.desc("id"))));
    }

    @AfterAuthentication
    @Override
    public AuthorityEntity getById(Long id) throws Exception {
        Optional<AuthorityEntity> optional = authorityDao.findById(id);
        if (optional.isEmpty()) {
            throw new IllegalAccessException("non-existent");
        }
        return optional.get();
    }

    @BeforeAuthentication
    @Transactional
    @Override
    public AuthorityEntity add(AuthorityEntity param) throws Exception {
        param.setId(null);
        for (String it : defaultCode) {
            if (param.getCode().toLowerCase(Locale.ENGLISH).contains(it)) {
                throw new IllegalAccessException("Code值 禁止使用");
            }
        }
        AuthorityEntity authorityEntity = authorityDao.findByCodeAndGid(param.getCode(), param.getGid());
        if (authorityEntity != null) {
            throw new IllegalAccessException("标签已经存在");
        }
        param.setGid(param.getGid());
        return authorityDao.save(param);
    }

    @Transactional
    @Override
    public AuthorityEntity set(AuthorityEntity param) throws Exception {
        AuthorityEntity entity = getById(param.getId());
        for (String it : defaultCode) {
            if (param.getCode().toLowerCase(Locale.ENGLISH).contains(it)) {
                throw new IllegalAccessException("Code值 禁止使用");
            }
        }

        AuthorityEntity oldEntity = authorityDao.findByCodeAndGid(param.getCode(),entity.getGid());
        if (oldEntity != null && entity.getId() != oldEntity.getId().longValue()) {
            throw new IllegalAccessException("权限Code重复");
        }

        if (!entity.getCode().equals(param.getCode())) { // 更换key值
            List<RoleAuthorityEntity> list = roleAuthorityDao.findAllByGidAndAuthorityCodeAndDelIsNull(entity.getGid(),entity.getCode());
            list.forEach(it -> it.setAuthorityCode(param.getCode()));
            roleAuthorityDao.saveAll(list);
            List<UserAuthorityEntity> all = userAuthorityDao.findAllByCodeGidAndAuthorityCode(entity.getGid(), entity.getCode());
            all.forEach(it -> it.setAuthorityCode(param.getCode()));
            userAuthorityDao.saveAll(all);
        }

        entity.setCode(param.getCode());
        entity.setName(param.getName());

        return authorityDao.save(entity);
    }

    @Transactional
    @Override
    public void del(Long id) throws Exception {
        AuthorityEntity entity = getById(id);
        LocalDateTime now = LocalDateTime.now();
        List<RoleAuthorityEntity> list = roleAuthorityDao.findAllByGidAndAuthorityCodeAndDelIsNull(entity.getGid(),entity.getCode());
        list.forEach(it -> it.setDel(now));
        roleAuthorityDao.saveAll(list);

        List<UserAuthorityEntity> all = userAuthorityDao.findAllByCodeGidAndAuthorityCode(entity.getGid(), entity.getCode());
        userAuthorityDao.deleteAll(all);

        authorityDao.delete(entity);
    }



}
